package model;
import model.game.Player;
import model.game.Skill;
import model.game.skills.Damageable;
import model.game.skills.Itself;
public class BattleBalance {
    private Player atk;
    private Player def;
    public BattleBalance(Player atk, Player def){
        this.atk = atk;
        this.def = def;
    }
    public int move(Skill skill, int bonus){
        if (skill instanceof Itself){
            Skill s = atk.findSkill(skill.getName());
            Itself i = (Itself)s;
            s.use();
            return -2;
        }
        if (skill instanceof Damageable){
            Damageable d = (Damageable)skill;
            if (!evasion(atk.getAgility(),d.getPrecision(), def.getAgility())) {
                if (critical(atk.getAptitude())){
                    double ataque = 1 + (int) (Math.random() * atk.getMajorAtribute());
                    double valorAtk = 2*d.getDamage() + ataque + bonus;
                    double valorArmor = armorFunction(def.getArmor());
                    valorArmor /= 100;
                    double finalDamage = valorAtk*(1-valorArmor);
                    int damageDone = (int) Math.round(finalDamage);
                    return damageDone;
                }else{
                    double ataque = 1 + (int) (Math.random() * atk.getMajorAtribute());
                    double valorAtk = d.getDamage() + ataque + bonus;
                    double valorArmor = armorFunction(def.getArmor());
                    valorArmor /= 100;
                    double finalDamage = valorAtk*(1-valorArmor);
                    int damageDone = (int) Math.round(finalDamage);
                    return damageDone;
                }
            }
            else {
                return -1;
            }            
        }
        return -99;
        
    }
    
    public int armorFunction(int x){
        double a=  Math.pow(x, 2);
        double b = a/4;
        double c = b+1;
        double d = 21;
        double y = Math.log10(c)*d;
        if (y<5){
            return 5;
        }else if (y>75){
            return 75;
        }
        return (int)y;
    }
    
    public int criticalFunction(int x){
        double a = Math.pow(x, 2);
        double b = a/40;
        double c = b+1;
        double d = 15;
        double y = Math.log(c)*d;
        if (y<5){
            return 5;
        }else if (y>50){
            return 50;
        }
        return (int) y;
    }
    
    public boolean evasion(int agilityAtk, int precisao, int agilityDef){
        int chance = 1 + (int) (Math.random() * 100);
        if (precisao !=0){
            if (chance <= 100 - precisao){
                return true;
            }else{
                return false;
            }
        }else{
        
            double soma = agilityAtk+agilityDef;
            double porc = (100/soma)*agilityDef;
            porc /= 2;
            if (porc > 30){
                porc = 30;
            }
            if (chance <= porc){
                return true;
            }else{
                return false;
            }
        }
    }
    
    public boolean critical(int destreza){
        int chance = 1 + (int) (Math.random() * 100);
        int critico = criticalFunction(destreza);
        if (chance <= critico){
            return true;
        }else{
            return false;
        }
    }
    
}
